package com.lazason.wib4android;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class AsyncImageLoader {
	private static final String tag = "AsyncImageLoader";
	private Context context;

	private HashMap<String, SoftReference<Drawable>> imageCache;
	 
	public AsyncImageLoader() {
		imageCache = new HashMap<String, SoftReference<Drawable>>();
		 
		// 线程池：最大10条，每次执行：1条，空闲线程结束的超时时间：180秒
		 
	}
	public void preDownload(final Context context, final String imageUrl,
			final String id, int priority){ 
			
			 
				
        Thread t = new Thread(){
        	@Override
			public void run() {
        		
				downloadImageFromUrl(context, imageUrl, id);
				
				
			}
        };
        t.setPriority(priority);
		// 用线程池来做下载图片的任务
		MyApplication.getExecutor().execute(t);
	}
	public Drawable loadDrawable(final Context context, final String imageUrl,
			final String id, int priority, final ImageCallback imageCallback) {
//		if (MyApplication.drawableCache.get(id) != null) {
//			Log.i(TAG,"file is exsisting in drawableCache");
//			return MyApplication.drawableCache.get(id);
//		}
		if (MyApplication.imageCache.containsKey(id)) {
			WeakReference<BitmapDrawable> softReference = MyApplication.imageCache.get(id);
			Drawable drawable = softReference.get();
			if (drawable != null) {
				return drawable; 
			}
		}
		
		final Handler handler = new Handler() {
			
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Drawable) message.obj, imageUrl, id);
				//Log.d("AsyncImageLoader", "id="+id);
			}
		};
		
        Thread t = new Thread(){
        	@Override
			public void run() {
        		
				Drawable drawable = loadImageFromUrl(context, imageUrl, id);
				//imageCache.put(id, new SoftReference<Drawable>(drawable));
				Message message = handler.obtainMessage(0, drawable);
				handler.sendMessage(message);
				
			}
        };
        t.setPriority(priority);
		// 用线程池来做下载图片的任务
        MyApplication.getExecutor().execute(t);
		
		return null;
	}
	
	
	public Bitmap loadBitMap(final Context context, final String imageUrl,
			final String id, int priority, final BitmapCallback bitmapCallback) {
//		if (MyApplication.drawableCache.get(id) != null) {
//			Log.i(TAG,"file is exsisting in drawableCache");
//			return MyApplication.drawableCache.get(id);
//		}
//		if (MyApplication.bitmapCache.containsKey(id)) {
//			WeakReference<Bitmap> softReference = MyApplication.bitmapCache.get(id);
//			Bitmap bitmap = softReference.get();
//			if (bitmap != null) {
//				return bitmap; 
//			}
//		}
		
		final Handler handler = new Handler() {
			
			public void handleMessage(Message message) {
				bitmapCallback.bitmapLoaded((Bitmap) message.obj, imageUrl, id);
				//Log.d("AsyncImageLoader", "id="+id);
			}
		};
		
        Thread t = new Thread(){
        	@Override
			public void run() {
        		
        		Bitmap bitmap = loadBitmapFromUrl(context, imageUrl, id);
				//imageCache.put(id, new SoftReference<Drawable>(drawable));
				Message message = handler.obtainMessage(0, bitmap);
				handler.sendMessage(message);
				
			}
        };
        t.setPriority(priority);
		// 用线程池来做下载图片的任务
        MyApplication.getExecutor().execute(t);
		
		return null;
	}
	public static void downloadImageFromUrl(Context context, String imageUrl,
			String id) {
		if (imageUrl == null)
			return ;
		String imagePath = "";
		String fileName = id;
		

		// 图片在手机本地的存放路径,注意：fileName为空的情况
		// imagePath = context.getCacheDir() + "/" + fileName;
		imagePath = context.getExternalCacheDir() + "/" + fileName;

		// Log.i(TAG,"imagePath = " + imagePath);
		File file = new File(context.getExternalCacheDir(), fileName);// 保存文件
//		 Log.i(tag,"file.toString()=" + file.toString());
		if (!file.exists() && !file.isDirectory()) {
			//Log.i(tag,"file is exsisting");
			try {
				long start = System.currentTimeMillis();
				// 可以在这里通过文件名来判断，是否本地有此图片
				FileOutputStream fos = new FileOutputStream(file);
				InputStream is = new URL(imageUrl).openStream();
				int data = is.read();
				while (data != -1) {
					fos.write(data);
					data = is.read();
					
				}
				fos.close();
				is.close();
				//long start = System.currentTimeMillis();
				long end  = System.currentTimeMillis();
				Log.d(tag, "save bitmap use time: "+(end-start));
				// drawable = Drawable.createFromStream(
				// new URL(imageUrl).openStream(), file.toString() ); //
				// (InputStream) new URL(imageUrl).getContent();
			
				// Log.i(TAG, "file.exists()不文件存在，网上下载:" + drawable.toString());
			} catch (IOException e) {
				Log.e(tag, e.toString() + "图片下载及保存时出现异常！");
				Log.e(tag, "imageUrl=" + imageUrl);
				Log.e(tag, "id=" + id);
			} catch (Exception e) {
				Log.e(tag, e.toString() + "图片下载及保存时出现异常！");
				Log.e(tag, "imageUrl=" + imageUrl);
				Log.e(tag, "id=" + id);
			}
		}
	}
	
	
	// 网络图片先下载到本地cache目录保存，以imagUrl的图片文件名保存。如果有同名文件在cache目录就从本地加载
	public static Drawable loadImageFromUrl(Context context, String imageUrl,
			String id) {
		 
		if (imageUrl == null)
			return null;
		String imagePath = "";
		String fileName = id;
		BitmapDrawable drawable = null;
		Bitmap bitMap = null;
		File cacheDirector = context.getExternalCacheDir();
		if(cacheDirector==null||!cacheDirector.exists()){
			bitMap =  downloadBitmapByUrl(imageUrl,0);
		}
		else {
		// 图片在手机本地的存放路径,注意：fileName为空的情况
		// imagePath = context.getCacheDir() + "/" + fileName;
		imagePath = context.getExternalCacheDir() + "/" + fileName;
		
		// Log.i(TAG,"imagePath = " + imagePath);
		File file = new File(context.getExternalCacheDir(), fileName);// 保存文件
		// Log.i(tag,"file.toString()=" + file.toString());
		if (!file.exists() && !file.isDirectory()) {
			 
			try {
				// 可以在这里通过文件名来判断，是否本地有此图片
				long start = System.currentTimeMillis();
				FileOutputStream fos = new FileOutputStream(file);
				InputStream is = new URL(imageUrl).openStream();
				int data = is.read();
				while (data != -1) {
					fos.write(data);
					data = is.read();
					
				}
				fos.close();
				is.close();
				//long start = System.currentTimeMillis();
				long end  = System.currentTimeMillis();
				Log.d(tag, "load and save bitmap use time: "+(end-start));
				// drawable = Drawable.createFromStream(
				// new URL(imageUrl).openStream(), file.toString() ); //
				// (InputStream) new URL(imageUrl).getContent();
				//drawable = Drawable.createFromPath(file.toString());
				
				
				
				// Log.i(TAG, "file.exists()不文件存在，网上下载:" + drawable.toString());
			} catch (IOException e) {
				Log.e(tag, e.toString() + "图片下载及保存时出现异常！");
				Log.e(tag, "imageUrl=" + imageUrl);
				Log.e(tag, "id=" + id);
			} catch (Exception e) {
				Log.e(tag, e.toString() + "图片下载及保存时出现异常！");
				Log.e(tag, "imageUrl=" + imageUrl);
				Log.e(tag, "id=" + id);
			}
		}  
		long start = System.currentTimeMillis();
		BitmapFactory.Options opts = new BitmapFactory.Options();
		//opts.inJustDecodeBounds = true;
		//BitmapFactory.decodeFile(file.toString(), opts);
		if("pi".equals(id.substring(0,2))||"pr".equals(id.substring(0,2))){
			opts.inSampleSize = 2;
		} else if("bf".equals(id.substring(0,2))){
			opts.inSampleSize = 1;
		} else {
			opts.inSampleSize = computeSampleSize(opts, -1, 800*480);
		}

		
		opts.inJustDecodeBounds = false;
//		 BitmapFactory.Options opts =new BitmapFactory.Options(); 
//		 opts.inSampleSize =2;
		 bitMap = BitmapFactory.decodeFile(file.toString(),opts);
		}
		 drawable = new BitmapDrawable(context.getResources(), bitMap);
		 WeakReference<BitmapDrawable> bitmapcache = new WeakReference<BitmapDrawable>(drawable) ;
		 MyApplication.imageCache.put(id,bitmapcache);
		//long start = System.currentTimeMillis();
			long end  = System.currentTimeMillis();
			//Log.d(tag, "read bitmap and put it into cache use time: "+(end-start));
		 return MyApplication.imageCache.get(id).get();
	}
	
	// 网络图片先下载到本地cache目录保存，以imagUrl的图片文件名保存。如果有同名文件在cache目录就从本地加载
	public   Bitmap loadBitmapFromUrl(Context context, String imageUrl,
			String id) {
		 
		if (imageUrl == null)
			return null;
		String imagePath = "";
		String fileName = id; 
		Bitmap bitMap = null;
		// 图片在手机本地的存放路径,注意：fileName为空的情况
		// imagePath = context.getCacheDir() + "/" + fileName;
		File cacheDirector = context.getExternalCacheDir();
		if(cacheDirector==null||!cacheDirector.exists()){
			return downloadBitmapByUrl(imageUrl,0);
		}
		imagePath = context.getExternalCacheDir() + "/" + fileName;

		// Log.i(TAG,"imagePath = " + imagePath);
		File file = new File(context.getExternalCacheDir(), fileName);// 保存文件
		
		// Log.i(tag,"file.toString()=" + file.toString());
		BitmapFactory.Options opts = new BitmapFactory.Options();
		//opts.inJustDecodeBounds = true;
		//BitmapFactory.decodeFile(file.toString(), opts);
		if("pi".equals(id.substring(0,2))||"pr".equals(id.substring(0,2))){
			opts.inSampleSize = 2;
		} else if("bf".equals(id.substring(0,2))){
			opts.inSampleSize = 1;
		} else {
			opts.inSampleSize = computeSampleSize(opts, -1, 480*480);
			//opts.inSampleSize = 2;
		}

		if (!file.exists() && !file.isDirectory()) {
			 
			try {
				// 可以在这里通过文件名来判断，是否本地有此图片
				
//				
//				FileOutputStream fos = new FileOutputStream(file);
//				InputStream is = new URL(imageUrl).openStream();
//				int data = is.read();
//				while (data != -1) {
//					fos.write(data);
//					data = is.read();
//					
//				}
//				fos.close();
//				is.close();
				// drawable = Drawable.createFromStream(
				// new URL(imageUrl).openStream(), file.toString() ); //
				// (InputStream) new URL(imageUrl).getContent();
				//drawable = Drawable.createFromPath(file.toString());
				
				  downloadBitmapAndSave(imageUrl,file, id);
				
				// Log.i(TAG, "file.exists()不文件存在，网上下载:" + drawable.toString());
			} catch (Exception e) {
				Log.e(tag, e.toString() + "图片下载及保存时出现异常！");
				 
				Log.e(tag, "imageUrl=" + imageUrl);
				Log.e(tag, "id=" + id);
				e.getStackTrace();
				return null;
			}
		} 
		   if (file.exists()) {  
			   
	            FileInputStream fis = null;  
	  
	            try {
					fis = new FileInputStream(file);
					if(fis.available()==0){
						file.delete();
						  downloadBitmapAndSave(imageUrl,file, id);
					}
					if(fis.available()>1024*1024*2){
						opts.inSampleSize = 4;
					} else if(fis.available()>1024*512){
						opts.inSampleSize = 2;
					}
					if(MyApplication.imageInfos.get(id)!=null){
						int width=MyApplication.imageInfos.get(id).width;
						int height=MyApplication.imageInfos.get(id).height;
						if((float)(height/width)>2){
							if(opts.inSampleSize>1){
								opts.inSampleSize = opts.inSampleSize/2;
							}
						}
						Log.d(tag, "width= "+width+";height="+height);
					}
					
					Log.d(tag, "file size : "+fis.available());
					Log.d(tag, "file size : "+fis.available());
					Log.d(tag, "opts.inSampleSize : "+opts.inSampleSize);
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}  
	  
	             
	               
	        } else {  
	            Log.d(tag, "can't access :"+imageUrl);
	            Log.d(tag, "file not exist :"+file.getName());
	        }
			opts.inJustDecodeBounds = false;
//			 BitmapFactory.Options opts =new BitmapFactory.Options(); 
//			 opts.inSampleSize =2;
			try{
			 bitMap = BitmapFactory.decodeFile(file.toString(),opts);
			} catch(Exception e){
				  FileInputStream in;
			        BufferedInputStream buf;
				  try {
					in = new FileInputStream(file.toString());
					  buf = new BufferedInputStream(in);
			            bitMap=  BitmapFactory.decodeStream(buf);
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
					Log.d(tag, e1.getMessage());
				   // downloadBitmapAndSave(imageUrl,file);
				}
		          
		             
			
			 //WeakReference<Bitmap> bitmapcache = new WeakReference<Bitmap>(bitMap) ;
			// MyApplication.bitmapCache.put(id,bitmapcache);
			}
			 return bitMap;
			 
	
	}
	public static int computeSampleSize(BitmapFactory.Options options,
	        int minSideLength, int maxNumOfPixels) {
	    int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels);

	    int roundedSize;
	    if (initialSize <= 8 ) {
	        roundedSize = 1;
	        while (roundedSize < initialSize) {
	            roundedSize <<= 1;
	        }
	    } else {
	        roundedSize = (initialSize + 7) / 8 * 8;
	    }

	    return roundedSize;
	}

	private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
	    double w = options.outWidth;
	    double h = options.outHeight;

	    if(w > h*4||h>w*4){
	    	return 1;
	    }
	    
	    int lowerBound = (maxNumOfPixels == -1) ? 1 :
	            (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
	    int upperBound = (minSideLength == -1) ? 128 :
	            (int) Math.min(Math.floor(w / minSideLength),
	            Math.floor(h / minSideLength));

	    if (upperBound < lowerBound) {
	        // return the larger one when there is no overlapping zone.
	        return lowerBound;
	    }

	    if ((maxNumOfPixels == -1) &&
	            (minSideLength == -1)) {
	        return 1;
	    } else if (minSideLength == -1) {
	        return lowerBound;
	    } else {
	        return upperBound;
	    }
	}
	public interface ImageCallback {
		public void imageLoaded(Drawable imageDrawable, String imageUrl,
				String id);
	}
	public interface BitmapCallback {
		public void bitmapLoaded(Bitmap bitmap, String imageUrl,
				String id);
	}
	public  static Bitmap downloadBitmapByUrl(String imageUrl,int retry){
		
		Bitmap response = null;
		try {
			long start = System.currentTimeMillis();
			URL url = new URL(imageUrl);
			URLConnection connection = url.openConnection();
			connection.setUseCaches(true);
			response = BitmapFactory.decodeStream((InputStream)connection.getContent());
			//long start = System.currentTimeMillis();
			long end  = System.currentTimeMillis();
			Log.d(tag, "save bitmap use time: "+(end-start));
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			
			Log.d(tag, e.getMessage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			Log.d(tag, e.getMessage());
		} catch (Exception e){
			Log.d(tag, e.getMessage());
		}
		if(retry>0){
			Log.d(tag, "retry:"+retry);
		}
		if(response==null&&retry<3) {
			retry++;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		    return downloadBitmapByUrl(imageUrl, retry);
		}
		return response;
		
	}
	public   void downloadBitmapAndSave(String imageUrl,final File file, String id){
		final Bitmap bitmap  = downloadBitmapByUrl(imageUrl,0);
		if(bitmap==null){
			return  ;
		}
		final long pre = System.currentTimeMillis();
	
//		Thread t = new Thread(){
//        	@Override
//			public void run() {  
//        		try {
//        			long start = System.currentTimeMillis();
//        			Log.d(tag, "save bitmap waiting time: "+(start-pre));
//        			
//        			
//					FileOutputStream fos = new FileOutputStream(file);
//				    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
//				    bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);  
//				     
//					fos.write(baos.toByteArray());
//					//long start = System.currentTimeMillis();
//					long end  = System.currentTimeMillis();
//				//	Log.d(tag, "save bitmap use time: "+(end-start));
//				} catch (FileNotFoundException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				} catch (IOException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
//        };
//        t.setPriority(Thread.MIN_PRIORITY);
//		// 用线程池来做下载图片的任务
//        MyApplication.getExecutor().execute(t);
        
        try {
			long start = System.currentTimeMillis();
			Log.d(tag, "save bitmap waiting time: "+(start-pre));
			
			
			FileOutputStream fos = new FileOutputStream(file);
		    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
		    bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);  
		     
			fos.write(baos.toByteArray());
			//long start = System.currentTimeMillis();
			long end  = System.currentTimeMillis();
		//	Log.d(tag, "save bitmap use time: "+(end-start));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ImageInfo imageInfo = new ImageInfo();
		imageInfo.height = bitmap.getHeight();
		imageInfo.width = bitmap.getWidth();
		 
		MyApplication.imageInfos.put(id, imageInfo);
		if(!bitmap.isRecycled()){
			bitmap.recycle();
		}
		return;
	}
	
}
